//------------------------------------------------------------------------------
///
///	\file debug.c
///
///	\brief
///		Debug implementation file
///
//	$Id: $
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//	The MIT License (MIT)
//
//	Copyright (c) 2014 A.C. Verbeck
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.

//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//	THE SOFTWARE.
//------------------------------------------------------------------------------
#include <windows.h>

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>

#include <stdint.h>
#include <stdbool.h>

#include "debug.h"

#define	TS_BUFFLEN    64
#define	TR_BUFFLEN    1024

static char trace_fmt[TR_BUFFLEN];
static char trace_str[TR_BUFFLEN];
static bool pr = false;

void TRACE_init(bool in)
{
	pr = in;
	if (pr == true)	printf("trace enabled\n");
}
//------------------------------------------------------------------------------
// _TR: trace function
//
// For debug builds (BLD_DEBUG), displays file, line, and string info.
// For release builds it does nothing (via macro definition in debug.h).
//
//  tr_lvl	- Trace level of message
//  file	- file name where trace message API is being called
//  func	- function name where trace message API is being called
//  line	- line number where trace message API is being called
//  ...		- va_args and formatting eters like for printf()/sprintf()
//------------------------------------------------------------------------------
void _TR(TRACE_LEVEL tr_lvl, const char* file, const char* func, uint16_t line, ...)
{
	va_list 	ap;
	char*		format;
	time_t		t;
	struct tm*	ptm;

	if (pr == false) return;

	va_start(ap, line);
	format = va_arg(ap, char*);
	snprintf(trace_fmt, TR_BUFFLEN, "%s:%d (%s) %s", file, line, func, format);
	vsnprintf(trace_str, TR_BUFFLEN, trace_fmt, ap);
	va_end(ap);

	time(&t);
	ptm = localtime(&t);
	printf("%02d:%02d:%02d ", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
	printf("%s\n", trace_str);
}

//------------------------------------------------------------------------------
// _TR_entry: trace entry function
//
// For debug builds (BLD_DEBUG), function entry information.
// For release builds it does nothing (via macro definition in debug.h).
//
//  file	- file name where trace message API is being called
//  func	- function name where trace message API is being called
//  line	- line number where trace message API is being called
//------------------------------------------------------------------------------
void _TR_entry(const char* file, const char* func)
{
	time_t		t;
	struct tm*	ptm;

	if (pr == false) return;

	time(&t);
	ptm = localtime(&t);
	printf("time:%02d:%02d:%02d ", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
	printf("file:%s function:%s (entry)\n", file, func);
}

//------------------------------------------------------------------------------
// _TR_exit: trace exit function
//
// For debug builds (BLD_DEBUG), displays function exit information
// For release builds it does nothing (via macro definition in debug.h).
//
//  file	- file name where trace message API is being called
//  func	- function name where trace message API is being called
//  line	- line number where trace message API is being called
//------------------------------------------------------------------------------
void _TR_exit(const char* file, const char* func)
{
	time_t		t;
	struct tm*	ptm;

	if (pr == false) return;

	time(&t);
	ptm = localtime(&t);
	printf("time:%02d:%02d:%02d ", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
	printf("file:%s function:%s (exit)\n", file, func);
}

//------------------------------------------------------------------------------
// ErrorExit: Get last error from Windows and exit
//
// Displays that last error message from windows, then exits.
//
// pfunc: function string
//------------------------------------------------------------------------------
void ErrorExit(const char* pfunc)
{
	char* lpMsgBuf = NULL;
	DWORD dw = GetLastError();

	FormatMessage(
	    FORMAT_MESSAGE_ALLOCATE_BUFFER |
	    FORMAT_MESSAGE_FROM_SYSTEM |
	    FORMAT_MESSAGE_IGNORE_INSERTS,
	    NULL,
	    dw,
	    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
	    (LPSTR)&lpMsgBuf,
	    0, NULL);

	printf("Function %s failed with error %lu: %s\n", pfunc, dw, lpMsgBuf);
	LocalFree(lpMsgBuf);
}

//
//	End: debug.c
//
